//------------------------------------------------------------------------------
//SFWK Framework
//Copyright (C) 2011 SQLI

//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program.  If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------

using System;
using System.Configuration;

namespace SFWK.Core.Unity
{

    /// <summary>
    /// Gives access to web.config's Unity configuration section
    /// </summary>
    public static class Configuration
    {       

        public static ServiceConfigElement GetServiceConfig(string serviceName)
        {
            return UnityConfigurationSection.Services[serviceName];
        }

        public static UnityConfigurationSection UnityConfigurationSection
        {
            get
            {
                UnityConfigurationSection config = (UnityConfigurationSection)System.Configuration.ConfigurationManager.GetSection("UnityConfiguration");

                return config;
            }
        }
    }

    /// <summary>
    /// Define a custom section named UrlsSection containing a
    /// ServicesCollection collection of ServiceConfigElement elements.
    /// The collection is wrapped in an element named "services" in the
    /// app.config file.
    /// ServicesCollection and ServicesConfigElement classes are defined below.
    /// </summary>
    public class UnityConfigurationSection : ConfigurationSection
    {
        /*
        <UnityConfiguration>
        <services defautlServiceLocation="http://localhost:8731/Design_Time_Addresses/">
            <clear />
            <add name="Logger" type="CMA.Common.ILogger, CMA.Common" localImplementation="CMA.Service.ServiceClient, CMA.Service.Implementation" />
            <add type="IParameterInspector, System.ServiceModel.Dispatcher"  localImplementation="CMA.Service.Inspector.InspectorParameter, CMA.Service.Inspector"/>			
            <add type="CMA.Service.IServiceClient, CMA.Service" localImplementation="CMA.Service.ImplementationSpecial"/>
            <add type="CMA.Service.*, CMA.Service" localImplementation="CMA.Service.Implementation"/>
            <add name="Compte" type="CMA.Service2.IServiceCompte, CMA.Service"  />
            <add name="Virement" type="CMA.Service.IServiceVirement, CMA.Service" endpointAddress="http://localhost:8731/Design_Time_Addresses/CMA.Service/ServiceVirement/"
             endpointBinding="wsHttpBinding" endpointContract="CMA.Service.IServiceVirement" />
        </services>
    </UnityConfiguration>         */
        [ConfigurationProperty("defautlServiceLocation", DefaultValue = "", IsRequired = false)]
        public string DefautlServiceLocation
        {
            get
            {
                return (string)this["defautlServiceLocation"];
            }
            set
            {
                this["defautlServiceLocation"] = value;
            }
        }
        [ConfigurationProperty("iisHosted", DefaultValue = "false", IsRequired = false)]
        public bool IISHosted
        {
            get
            {
                return (bool)this["iisHosted"];
            }
            set
            {
                this["iisHosted"] = value;
            }
        }
        /// <summary>
        /// Limit the received message size in Byte
        /// </summary>
        [ConfigurationProperty("maxReceivedMessageSize", DefaultValue = "66000", IsRequired = false)]
        public long MaxReceivedMessageSize
        {
            get
            {
                return (long)this["maxReceivedMessageSize"];
            }
            set
            {
                this["maxReceivedMessageSize"] = value;
            }
        }

        /// <summary>
        /// Limit the received message size in Byte
        /// </summary>
        [ConfigurationProperty("MaxItemsInObjectGraph", IsRequired = false)]
        public int MaxItemsInObjectGraph
        {
            get
            {
                return (int)this["MaxItemsInObjectGraph"];
            }
            set
            {
                this["MaxItemsInObjectGraph"] = value;
            }
        }
        
        /// <summary>
        /// Update the service operation Timeout in minutes
        /// </summary>
        [ConfigurationProperty("OperationTimeout", IsRequired = false)]
        public int OperationTimeout
        {
            get
            {
                return (int)this["OperationTimeout"];
            }
            set
            {
                this["OperationTimeout"] = value;
            }
        }
        

        // Declare the services collection property.
        // Note: the "IsDefaultCollection = false" instructs 
        // .NET Framework to build a nested section of 
        // the kind <services>...</services>.
        [ConfigurationProperty("services", IsDefaultCollection = false)]
        [ConfigurationCollection(typeof(ServicesCollection),
            AddItemName = "add",
            ClearItemsName = "clear",
            RemoveItemName = "remove")]
        public ServicesCollection Services
        {
            get
            {
                ServicesCollection servicesCollection =
                    (ServicesCollection)base["services"];
                return servicesCollection;
            }
        }

    }

    // Define the ServicesCollection that will contain the ServicesConfigElement
    // elements.
    public class ServicesCollection : ConfigurationElementCollection
    {
        public ServicesCollection()
        {
            // When the collection is created, always add one element 
            // with the default values. (This is not necessary; it is
            // here only to illustrate what can be done; you could 
            // also create additional elements with other hard-coded 
            // values here.)
            ServiceConfigElement service = (ServiceConfigElement)CreateNewElement();
            Add(service);
        }

        public override ConfigurationElementCollectionType CollectionType
        {
            get
            {
                return ConfigurationElementCollectionType.AddRemoveClearMap;
            }
        }

        protected override ConfigurationElement CreateNewElement()
        {
            return new ServiceConfigElement();
        }

        protected override Object GetElementKey(ConfigurationElement element)
        {
            return ((ServiceConfigElement)element).Type;
        }

        public ServiceConfigElement this[int index]
        {
            get
            {
                return (ServiceConfigElement)BaseGet(index);
            }
            set
            {
                if (BaseGet(index) != null)
                {
                    BaseRemoveAt(index);
                }
                BaseAdd(index, value);
            }
        }

        new public ServiceConfigElement this[string type]
        {
            get
            {
                return (ServiceConfigElement)BaseGet(type);
            }
        }

        public int IndexOf(ServiceConfigElement service)
        {
            return BaseIndexOf(service);
        }

        public void Add(ServiceConfigElement service)
        {
            BaseAdd(service);
        }
        protected override void BaseAdd(ConfigurationElement element)
        {
            BaseAdd(element, false);
        }

        public void Remove(ServiceConfigElement service)
        {
            if (BaseIndexOf(service) >= 0)
                BaseRemove(service.Type);
        }

        public void RemoveAt(int index)
        {
            BaseRemoveAt(index);
        }

        public void Remove(string type)
        {
            BaseRemove(type);
        }

        public void Clear()
        {
            BaseClear();
        }
    }

    // Define the element type contained by the ServicesCollection
    // collection.
    public class ServiceConfigElement : ConfigurationElement
    {
        public ServiceConfigElement(String type, String localImplementation, String endpointAddress, String endpointBinding, String endpointContract)
        {
            this.Type = type;
            this.LocalImplementation = localImplementation;
            this.EndpointAddress = endpointAddress;
            this.EndpointBinding = endpointBinding;
            this.EndpointContract = endpointContract;
        }

        public ServiceConfigElement()
        {
            // Attributes on the properties provide default values.
        }

        [ConfigurationProperty("type", DefaultValue = "", IsRequired = true, IsKey = true)]
        public string Type
        {
            get
            {
                return (string)this["type"];
            }
            set
            {
                this["type"] = value;
            }
        }

        [ConfigurationProperty("localImplementation", DefaultValue = "", IsRequired = false)]
        public string LocalImplementation
        {
            get
            {
                return (string)this["localImplementation"];
            }
            set
            {
                this["localImplementation"] = value;
            }
        }

        [ConfigurationProperty("useDataContext", DefaultValue = "false", IsRequired = false)]
        public bool UseDataContext
        {
            get
            {
                return (bool)this["useDataContext"];
            }
            set
            {
                this["useDataContext"] = value;
            }
        }

        [ConfigurationProperty("endpointAddress", DefaultValue = "", IsRequired = false)]
        public string EndpointAddress
        {
            get
            {
                return (string)this["endpointAddress"];
            }
            set
            {
                this["endpointAddress"] = value;
            }
        }
        [ConfigurationProperty("endpointBinding", DefaultValue = "WSHttpBinding", IsRequired = false)]
        public string EndpointBinding
        {
            get
            {
                return (string)this["endpointBinding"];
            }
            set
            {
                this["endpointBinding"] = value;
            }
        }
        [ConfigurationProperty("endpointContract", DefaultValue = "", IsRequired = false)]
        public string EndpointContract
        {
            get
            {
                return (string)this["endpointContract"];
            }
            set
            {
                this["endpointContract"] = value;
            }
        }
    }
}

